﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.IO;

namespace AppBrowser
{
    /// <summary>
    /// Class to store application data (xml or database)
    /// </summary>
    public class AppData
    {
        public static string AppDataPath = "";
        public static string AppDataFileName = "AppDatabase.xml";
        public static string AppXMLSaveFile = "AppDatabaseSAVE.xml";
        public static string ApplicationPath="";
        public static string AppCategoryPath = "";

        private DataSet appDataSet;
        public DataSet AppDataSet
        {
            get { return appDataSet; }
        }


        public AppData()
        {
            ApplicationPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);

            ApplicationPath = ApplicationPath.Replace("file:\\", "");
            try
            {
                // AppDataPath = Properties.Settings.Default.AppDataPath;
            } catch {
                
                AppDataPath = ApplicationPath + "\\AppData";
            }
            
            
            // work out application data path
            if (Directory.Exists(AppDataPath))
            {
                // AppDataPath = Properties.Settings.Default.AppDataPath;
            }
            else
            {
                // use applications path
                AppDataPath = ApplicationPath + "\\AppData";
            }
            
            AppDataFileName = AppDataPath + "\\" + AppDataFileName;
            AppXMLSaveFile = AppDataFileName;
            AppCategoryPath = AppDataPath + "\\Category";


            // attempt to load dataset
            appDataSet = new DataSet();
            appDataSet.ReadXml(AppDataFileName, XmlReadMode.InferSchema);
            PrintDataSet(appDataSet);
        }

        public void SaveXML()
        {
            try {
                appDataSet.WriteXml(AppXMLSaveFile, XmlWriteMode.WriteSchema);
            } catch {
                throw;
            }
        }

        public string GetDatabaseDate()
        {
            return appDataSet.Tables["Applications"].Rows[0]["databasedate"].ToString();
        }

        public DataTable GetApps()
        {
            return appDataSet.Tables["App"];
        }

        /// <summary>
        /// Return true if ver2 is newer than ver1
        /// </summary>
        /// <param name="ver1"></param>
        /// <param name="Ver2"></param>
        /// <returns></returns>
        public bool CompareVersion(string ver1, string ver2)
        {
            

            ver1 = System.Text.RegularExpressions.Regex.Replace(ver1, "[^0-9|^.]", "");
            ver2 = System.Text.RegularExpressions.Regex.Replace(ver2, "[^0-9|^.]", "");

            try
            {
                Version v1 = new Version(ver1);
                Version v2 = new Version(ver2);

                if (v1 < v2)
                {
                    return true;
                }
            }
            catch { }

            return false;
        }

        /// <summary>
        /// Add Application Item to dataset
        /// </summary>
        /// <param name="app"></param>
        public void AddAppItem(AppItem app)
        {
            DataRow dr = appDataSet.Tables["App"].NewRow();
            app.App_Id = dr["App_Id"].ToString();
            dr["name"] = app.AppName;
            dr["Category_Id"] = app.Category_Id;
            dr["license"] = app.License;
            dr["publisher"] = app.Publisher;
            dr["publisherDesc"]= app.PublisherDesc;
            dr["publisherUrl"] = app.PublisherUrl;
            dr["sysreqs"] = app.SystemRequirements;
            dr["description"] = app.Description;

            appDataSet.Tables["App"].Rows.Add(dr);
            // add versions ----------------------------------
            DataRow vRow = appDataSet.Tables["VersionHistory"].NewRow();
            vRow["App_Id"] = app.App_Id;

            // get version container
            string VersionHistory_Id = vRow["VersionHistory_Id"].ToString();

            appDataSet.Tables["VersionHistory"].Rows.Add(vRow);

            // add versions
            foreach (AppVersion appVer in app.VersionList)
            {
                DataRow avRow = appDataSet.Tables["AppVersion"].NewRow();
                avRow["VersionHistory_Id"] = VersionHistory_Id;
                avRow["version"] = appVer.VersionNumber;
                avRow["versionType"] = appVer.VersionType;
                avRow["filename"] = appVer.FileName;
                avRow["VersionDownloadUrl"] = appVer.DownloadUrl;
                avRow["VersionDescription"] = appVer.VersionDescription;

                appDataSet.Tables["AppVersion"].Rows.Add(avRow);
            }
            // ---------------- versions -----------------------
        }

        /// <summary>
        /// Add Application Item to dataset
        /// </summary>
        /// <param name="app"></param>
        public void UpdateAppItem(AppItem app)
        {
            DataRow[] drs = appDataSet.Tables["App"].Select("App_Id='"+app.App_Id+"'");
            DataRow dr = drs[0];          
            
            dr["name"] = app.AppName;
            dr["Category_Id"] = app.Category_Id;
            dr["license"] = app.License;
            dr["publisher"] = app.Publisher;
            dr["publisherDesc"] = app.PublisherDesc;
            dr["publisherUrl"] = app.PublisherUrl;
            dr["sysreqs"] = app.SystemRequirements;
            dr["Description"] = app.Description;

            dr.AcceptChanges();
            
            // appDataSet.Tables["App"].Rows.Add(dr);
            // add versions ----------------------------------
            DataRow[] vRow = appDataSet.Tables["VersionHistory"].Select("App_Id='" + app.App_Id + "'");

            // get version container
            string VersionHistory_Id = vRow[0]["VersionHistory_Id"].ToString();

            // grab version rows from ds
            DataRow[] avRows = appDataSet.Tables["AppVersion"].Select("VersionHistory_Id='" + VersionHistory_Id + "'");
            int cnt = -1;
            // add versions
            foreach (AppVersion appVer in app.VersionList)
            {
                cnt++;
                DataRow avRow;
                if (cnt>avRows.Length-1)
                {
                    // doesnt exist so make new one
                    avRow = appDataSet.Tables["AppVersion"].NewRow();
                    avRow["VersionHistory_Id"] = VersionHistory_Id;
                    avRow["version"] = appVer.VersionNumber;
                    avRow["versionType"] = appVer.VersionType;
                    avRow["filename"] = appVer.FileName;
                    avRow["VersionDownloadUrl"] = appVer.DownloadUrl;
                    avRow["VersionDescription"] = appVer.VersionDescription;
                    appDataSet.Tables["AppVersion"].Rows.Add(avRow);
                }
                else
                {
                    // exists, so modify it
                    avRow = avRows[cnt];
                    avRow["VersionHistory_Id"] = VersionHistory_Id;
                    avRow["version"] = appVer.VersionNumber;
                    avRow["versionType"] = appVer.VersionType;
                    avRow["filename"] = appVer.FileName;
                    avRow["VersionDownloadUrl"] = appVer.DownloadUrl;
                    avRow["VersionDescription"] = appVer.VersionDescription;
                    avRow.AcceptChanges();
                }
            }
            // ---------------- versions -----------------------
        }


 

        /// <summary>
        /// returns complete app item with versions
        /// </summary>
        /// <param name="App_Id"></param>
        /// <returns></returns>
        public AppItem GetAppItem(string App_Id)
        {
            DataRow[] dr = appDataSet.Tables["App"].Select("App_Id='" + App_Id + "'");

            if (dr.Length > 0)
            {
                // create new appitem with data from datarow
                AppItem nApp = new AppItem(dr[0]);

                // now add category name
                dr = appDataSet.Tables["Category"].Select("Category_Id='" + nApp.Category_Id + "'");
                nApp.Category = dr[0]["name"].ToString();

                // now add list of versions
                nApp.AddVersions(this.GetAppVersions(Convert.ToInt32(App_Id)));

                return nApp;
            }

            return null;
        }

        /// <summary>
        /// Get DataRow Application
        /// </summary>
        /// <param name="App_Id"></param>
        /// <returns></returns>
        public DataRow GetAppRow(string App_Id)
        {
            DataRow[] dr = appDataSet.Tables["App"].Select("App_Id='" + App_Id + "'");
            if (dr.Length > 0)
            {
                return dr[0];
            }
            return null;
        }

        public DataRow[] SearchAppsByName(string searchQ)
        {
            DataRow[] dr = appDataSet.Tables["App"].Select("name LIKE '%" + searchQ + "%'");
            return dr;

        }

        public DataTable GetCategories()
        {
            return appDataSet.Tables["Category"];
        }

        public DataTable GetVersions()
        {
            return appDataSet.Tables["AppVersion"];
        }

        public DataRow[] GetAllApps()
        {
            DataRow[] dr = appDataSet.Tables["App"].Select();
            return dr;
        }

        public DataRow[] GetAppsByLicenseType(string license,string category)
        {
            DataRow[] dr = appDataSet.Tables["App"].Select("license='" + license + "' AND Category_Id='"+category+"'");
            return dr;
        }

        public DataRow[] GetAppsByLicenseType(string license)
        {
            DataRow[] dr = appDataSet.Tables["App"].Select("license='" + license + "'");
            return dr;
        }


        /// <summary>
        /// Get Icon  for Categories from IconFile Specified (.exe / .ico )
        /// </summary>
        /// <param name="IconFile"></param>
        /// <returns></returns>
        public System.Drawing.Icon GetCatIconFromFile(string IconFile)
        {
            IconFile = AppCategoryPath + "\\" + IconFile;
            IconFile = IconFile.ToString().TrimStart(new char[] {'\\'});
            if (File.Exists(IconFile))
            {
                // return IconExtract.ExtractIconFromFile(IconFile);
            }
            else
            {
                // System.Windows.Forms.MessageBox.Show("Unable to load Icon : " + IconFile);

            }
            return null;
        }

 

        /// <summary>
        /// Build Versions Type(s) from version releases
        /// </summary>
        /// <returns></returns>
        public List<string> BuildVersionTypeList()
        {
            DataTable dt = appDataSet.Tables["AppVersion"];
            List<string> VersionList = new List<string>();
            foreach (DataRow dr in dt.Rows)
            {
                bool fnd=false;
                string versionType = dr["versionType"].ToString();

                foreach (string s in VersionList)
                {
                    if (s == versionType)
                    {
                        fnd = true;
                        break;
                    }
                }

                if (!fnd && versionType!="")
                {
                    VersionList.Add(versionType);
                } 
            }
            return VersionList;
        }

        public List<string> BuildLicenseList()
        {
            DataTable dt = appDataSet.Tables["App"];
            List<string> aList = new List<string>();
            foreach (DataRow dr in dt.Rows)
            {
                bool fnd = false;
                string licenseType = dr["license"].ToString();

                foreach (string s in aList)
                {
                    if (s == licenseType)
                    {
                        fnd = true;
                        break;
                    }
                }

                if (!fnd && licenseType != "")
                {
                    aList.Add(licenseType);
                }
            }
            return aList;
        }

        public string[] BuildLicenseArray()
        {
            List<string> l = BuildLicenseList();
            string[] ret = new string[l.Count];
            int cnt=0;
            foreach (string s in l)
            {
                ret[cnt] = s;
                cnt++;
            }
            return ret;
        }

        public DataRow[] GetAppsByCategory(string category)
        {
            // find correct row
            DataTable dt = appDataSet.Tables["Category"];
            DataTable rdt = new DataTable("Apps");
            DataRow[] drs= new DataRow[1];  

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                if (dt.Rows[i]["name"].ToString() == category)
                {
                    // found category, return child rows
                    drs = dt.Rows[i].GetChildRows(dt.ChildRelations["Category_App"]);
                }
            }
            return drs;
        }

        /// <summary>
        /// Get Versions for and Application from ID
        /// ID's generated automatically from readxml as App_Id
        /// </summary>
        /// <param name="App_Id"></param>
        /// <returns></returns>
        public DataRow[] GetAppVersions(int App_Id)
        {
            DataTable AppTable = GetApps();

            try
            {
                // find correct data
                DataRow[] drs = new DataRow[1];
                DataTable VersionHistory = appDataSet.Tables["VersionHistory"];

                // get VersionHistory rows for this app_id, to gather VersionHistory_Id
                drs = VersionHistory.Select("App_Id='" + App_Id + "'");
                int VersionHistory_Id = Convert.ToInt32(drs[0]["VersionHistory_Id"].ToString());

                // now gather version rows
                drs = VersionHistory.Rows[VersionHistory_Id].GetChildRows(VersionHistory.ChildRelations["VersionHistory_AppVersion"]);
                return drs;
            }
            catch
            {
                return null;
            }
        }

        public static void PrintDataSet(DataSet ds)
        {
            // Print out all tables and their columns  
            foreach (DataTable table in ds.Tables)
            {
                Console.WriteLine("TABLE '{0}'", table.TableName);
                Console.WriteLine("Total  of rows: {0}", table.Rows.Count);
                Console.WriteLine("---------------------------------------------------------------");

                foreach (DataColumn column in table.Columns)
                {
                    Console.WriteLine("- {0} ({1})", column.ColumnName, column.DataType.ToString());
                }  // foreach column  

                Console.WriteLine(System.Environment.NewLine);
            }  // foreach table  

            // Print out table relations  
            foreach (DataRelation relation in ds.Relations)
            {
                Console.WriteLine("RELATION: {0}", relation.RelationName);
                Console.WriteLine("---------------------------------------------------------------");
                Console.WriteLine("Parent: {0}", relation.ParentTable.TableName);
                Console.WriteLine("Child: {0}", relation.ChildTable.TableName);
                Console.WriteLine(System.Environment.NewLine);
            }  // foreach relation  
        }       
    
    }

}
